import {LinkOption} from "./LinkOption.ts";
import {EPoint} from "./EPoint.ts";

/**
 * 自动垂直或水平
 * @param {eventX, eventY}
 * @param linkOption
 * @param point
 */
function correctHV({eventX, eventY}, linkOption: LinkOption, point: EPoint) {
    let mousePoint = new EPoint(eventX, eventY);
    let points = linkOption.points;
    let pointIndex = points.indexOf(point);
    let isStart = pointIndex === 0;
    let isEnd = pointIndex === points.length - 1;
    //找到前后两个点
    let previousPoint: EPoint | null = isStart ? null : points[pointIndex - 1];
    let nextPoint: EPoint | null = isEnd ? null : points[pointIndex + 1];
    let changeY = false;
    let changeX = false;
    //如果两个点差不多垂直
    if (nearH(mousePoint, previousPoint)) {
        point.y = previousPoint.y
        changeY = true
    }
    if (nearH(mousePoint, nextPoint)) {
        point.y = nextPoint.y
        changeY = true
    }
    if (nearV(mousePoint, previousPoint)) {
        point.x = previousPoint.x
        changeX = true
    }
    if (nearV(mousePoint, nextPoint)) {
        point.x = nextPoint.x
        changeX = true
    }
    if (!changeX) {
        point.x = eventX;
    }
    if (!changeY) {
        point.y = eventY;
    }
}

/**
 * 判断两个点的连线是否接近水平
 * @param point 本点
 * @param pointOther 关联的点
 */
function nearH(point: EPoint, pointOther: EPoint) {
    if (pointOther == null) {
        return false;
    }
    let deltaYRes = (Math.abs(point.y - pointOther.y)) <= 5;
    let deltaA = Math.atan(Math.abs((point.y - pointOther.y) / (point.x - pointOther.x))) < Math.PI / 180 * 5
    return deltaA && deltaYRes
}

/**
 * 判断两个点的连线是否接近垂直
 * @param point 本点
 * @param pointOther 关联的点
 */
function nearV(point: EPoint, pointOther: EPoint) {
    if (pointOther == null) {
        return false;
    }
    let deltaXRes = (Math.abs(point.x - pointOther.x)) <= 5
    let deltaA = Math.atan(Math.abs((point.x - pointOther.x) / (point.y - pointOther.y))) < Math.PI / 180 * 5
    return deltaA && deltaXRes
}

function flow2int(n: number) {
    return n;
    // return Math.round(n / 10) * 10
}

function fromBinary(binary) {
    const bytes = new Uint8Array(binary.length);
    for (let i = 0; i < bytes.length; i++) {
        bytes[i] = binary.charCodeAt(i);
    }
    const charCodes = new Uint16Array(bytes.buffer);
    let result = "";
    for (let i = 0; i < charCodes.length; i++) {
        result += String.fromCharCode(charCodes[i]);
    }
    return result;
}

function b2string(s: string) {
    let jsonStr = atob(s)
    jsonStr = jsonStr.trim()
    jsonStr = fromBinary(jsonStr)
    return jsonStr
}

function fromUnicode(uArray) {
    let res = ""
    for (let charCode of uArray) {
        let char = String.fromCharCode(charCode);
        res = res + char
    }
    return res
}

function distance2d(x1: number, y1: number, x2: number, y2: number) {
    return Math.sqrt(Math.pow((x2 - x1), 2) + Math.pow((y2 - y1), 2))
}

export {correctHV, flow2int, fromBinary, b2string, fromUnicode, distance2d}
